package com.luxk.db.common;

import java.util.Vector;

import com.luxk.db.errorcode.ErrorCodeServer;
import com.luxk.db.server.Server;
import com.luxk.db.server.ShutdownMode;
import com.luxk.db.server.StartupMode;
import com.luxk.db.tests.UnitTest;

public abstract class ModuleBase implements Module {
	
	protected String name = null;
	protected Server server = null;
	protected Module parent = null;
	protected Vector<Module> subModules = new Vector<Module>();
	
	protected StartupMode curMode = StartupMode.NONE;

	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setServer(Server server) {
		this.server = server;
	}

	public void setParent(Module module) {
		this.parent = module;
	}

	public void addSubModule(Module module) {
		if(this.getName() == null || "".equals(this.getName())) {
			throw new NullPointerException(
					"Module " + this.getClass().getName() + " name is null");
		}

		if(module.getName() == null || "".equals(module.getName())) {
			throw new NullPointerException(
					"Module " + module.getClass().getName() + " name is null");
		}

		this.subModules.add(module);
	}
	
	public void runTest(StartupMode mode) throws Exception {
		
		UnitTest test = getUnitTest();
		
		if(test == null) {
			System.out.println("# Module " + this.name + " has no test");
			return;
		}
		
		System.out.println("# Module " + this.name + " begin unit test with " +
				mode.getStrVal() + " mode...");
		
		test.setTestObject(this);
		
		switch(mode) {
		case NONE:
			break;
		case NOMOUNT:
			test.testNomount();
			break;
		case MOUNT:
			test.testMount();
			break;
		case STANDBY:
			test.testStandby();
			break;
		case NORMAL:
			test.testNormal();
			break;
		default:
			/* do nothing */
		}
	}
	
	protected Server getServer() {
		return this.server;
	}
	
	protected Module getSubModule(String name) throws Exception {
		for(Module e: this.subModules) {
			if(e.getName().equals(name)) return e;
		}
		throw new NullPointerException("Module " + name + " not found");
	}

	public void raise(StartupMode mode) throws Exception {
		switch(mode) {
		case NONE:
			break;
		case NOMOUNT:
			if(this.curMode != StartupMode.NONE)
				throw new ImpactException(
						ErrorCodeServer.ERROR_RAISE_SERVER_MODE,
						curMode.getStrVal(), mode.getStrVal());
			raiseNomount();
			this.curMode = StartupMode.NOMOUNT;
			break;
		case MOUNT:
			if(this.curMode != StartupMode.NOMOUNT)
				throw new ImpactException(
						ErrorCodeServer.ERROR_RAISE_SERVER_MODE,
						curMode.getStrVal(), mode.getStrVal());
			raiseMount();
			this.curMode = StartupMode.MOUNT;
			break;
		case STANDBY:
			if(this.curMode != StartupMode.MOUNT)
				throw new ImpactException(
						ErrorCodeServer.ERROR_RAISE_SERVER_MODE,
						curMode.getStrVal(), mode.getStrVal());
			raiseStandby();
			this.curMode = StartupMode.STANDBY;
			break;
		case NORMAL:
			if(this.curMode != StartupMode.MOUNT &&
				this.curMode != StartupMode.STANDBY)
				throw new ImpactException(
						ErrorCodeServer.ERROR_RAISE_SERVER_MODE,
						curMode.getStrVal(), mode.getStrVal());
			raiseNormal();
			this.curMode = StartupMode.NORMAL;
			break;
		default:
			// LOG(warning, invalid startup mode);
		}
	}

	public void cancelRaise() throws Exception {
		switch(this.curMode) {
		case NONE:
			break;
		case NOMOUNT:
			cancelNomount();
			this.curMode = StartupMode.NONE;
			break;
		case MOUNT:
			cancelMount();
			this.curMode = StartupMode.NOMOUNT;
			break;
		case STANDBY:
			cancelStandby();
			this.curMode = StartupMode.MOUNT;
			break;
		case NORMAL:
			cancelNormal();
			this.curMode = StartupMode.MOUNT; // MOUNT로 내려감에 주의!
			break;
		}
	}

	public abstract void init() throws Exception;
	
	public abstract void raiseNomount() throws Exception;
	public abstract void raiseMount() throws Exception;
	public abstract void raiseStandby() throws Exception;
	public abstract void raiseNormal() throws Exception;
	
	public abstract void cancelNomount() throws Exception;
	public abstract void cancelMount() throws Exception;
	public abstract void cancelStandby() throws Exception;
	public abstract void cancelNormal() throws Exception;
	
	public abstract void shutdown(ShutdownMode mode) throws Exception;
	
	public abstract UnitTest getUnitTest();

}
